package bizerror

import (
	"errors"
	"fmt"
	"runtime/debug"

	"gitee.com/shoyer/logger"
)

type BizError interface {
	error
	Code() int
	Data() interface{}
	Stack() string
	Print()
}

type bizError struct {
	error
	code  int
	data  interface{}
	stack string
}

func (e bizError) Code() int {
	return e.code
}

func (e bizError) Data() interface{} {
	return e.data
}

func (e bizError) Stack() string {
	return e.stack
}

func (e bizError) Print() {
	if e.Data() != nil {
		logger.ErrorfNoStack("\ncode = %d\nmessage = %s\ndata = %v%s", e.Code(), e.Error(), e.Data(), logger.Yellow(e.Stack()))
	} else {
		logger.ErrorfNoStack("\ncode = %d\nmessage = %s\n%s", e.Code(), e.Error(), logger.Yellow(e.Stack()))
	}
}

// NewBizError.
// code 默认为0,
// data只能有一个参数, 超过一个以上的参数无法正确处理，这里只是通过可变参数来实现类似默认参数的效果.
func NewBizError(message string, data ...interface{}) BizError {
	e := bizError{}
	e.error = errors.New(message)

	if data != nil && len(data) > 0 {
		e.data = data[0]
	}

	e.stack = fmt.Sprintf("\n%s", debug.Stack())

	return &e
}

// NewBizErrorWithCode
// 带错误码
func NewBizErrorWithCode(code int, message string, data ...interface{}) BizError {
	e := bizError{}
	e.code = code
	e.error = errors.New(message)

	if data != nil && len(data) > 0 {
		e.data = data[0]
	}

	e.stack = fmt.Sprintf("\n%s", debug.Stack())

	return &e
}
